# -*- coding:utf-8 -*-
"""
@Author : 审心
@Time : 2023/3/28 17:05
该模块公用资源
"""
from dataclasses import dataclass, field
import time
from typing import Optional, List

import pandas as pd
import pyperclip
from DrissionPage.action_chains import ActionChains
from DrissionPage.commons.keys import Keys

import common.glv as glv
from DrissionPage import WebPage
from DrissionPage.chromium_element import ChromiumElement
from DrissionPage.chromium_tab import ChromiumTab
from autoTask.taobao.sycm.utils.close_Ad import close_ad, tb_slider
from common.utils import StrUtil
from common.utils.ThreadUtil import before_enable_stop_abel_thread
from common.utils.web_page_util import wait_ele_disappear, action_lock, Tap

__links = {
    '品类_商品排行': "https://sycm.taobao.com/cc/item_rank",
    '生意参谋首页': 'https://sycm.taobao.com/portal/home.htm',
    '市场_市场排行_商品': "https://sycm.taobao.com/mc/mq/market_rank?activeKey=item",
    '市场_搜索分析_相关分析': 'https://sycm.taobao.com/mc/mq/search_analyze?activeKey=relation',
    '竞争_竞品分析': "https://sycm.taobao.com/mc/ci/item/analysis",
    '竞争_竞品配置_商品': "https://sycm.taobao.com/mc/ci/config/rival?activeKey=item",
}

# 关键词搜索分析缓存 (任务运行完需要清空)
glv.set_item("关键词搜索分析缓存", pd.DataFrame())


@dataclass
class GoodsFeature:
    """
    商品特征
    Attributes:
        goods_id (int): 商品编号
        price_scope (float) : 客单价区间
        date_cycle: 数据周期
        competing1: 一号竞品
        competing2: 二号竞品
    """
    goods_id: Optional[int] = None
    price_scope: Optional[List[float]] = None
    date_cycle: str = '30天'
    competing1: str = ''
    competing2: str = ''

    def set_by_page(self, page: [WebPage, ChromiumTab], goods_id: int):
        self.goods_id = int(goods_id)
        # 天猫商品
        if "tmall.com" in page.url:
            e = page(".Price--priceText--2nLbVda Price--extraPriceText--2dbLkGw", timeout=0)
            if e:
                self.price_scope = [float(e.text), float(e.text)]
            else:
                price = float(page(".Price--priceText--2nLbVda", timeout=10).text)
                self.price_scope = [price, price]
        # 淘宝商品
        elif "taobao.com" in page.url:
            e = page("#J_PromoPriceNum")
            if e:
                price = float(e.text.split("-")[0])
                self.price_scope = [price, price]
            if page("t:strong@@text():此宝贝已下架"):
                return None
        # 防止出现滑块但没有验证
        tb_slider(page)
        return self


@dataclass
class MonitorCompetingProduct:
    """
    监控竞争产品类，包括以下成员属性:
    Attributes:
        title (str): 竞争产品的标题。
        link (str): 竞争产品的链接。
        date (str): 竞争产品的发布日期。
        id (int): 竞争产品的唯一标识符。
        cancel_ele (ChromiumElement): 取消监控按钮的Web元素对象。如果没有提供，则默认为None。
    """

    title: str
    link: str
    date: str
    id: int
    cancel_ele: ChromiumElement


@dataclass
class CategorySearch:
    """
    品类搜索对象
    Attributes:
      name (str): 品类名称。
      ignore_name_list (List[str]): 忽略商品名称包含此列表中字符串的商品。
      contain_name_list (List[str]): 忽略商品名称不包含此列表中字符串的商品。
      goods_feature_list (List[GoodsFeature]): 商品特征列表。
    """
    name: str
    date_cycle: str
    ignore_name_list: List[str] = field(default_factory=list)
    contain_name_list: List[str] = field(default_factory=list)
    goods_feature_list: List[GoodsFeature] = field(default_factory=list)

    @staticmethod
    def init_by_dict(dict_: dict, goods_target_key: str, category_key: str):
        """
        根据字典初始化
        :param dict_: 字典
        :param category_key:品类
        :param goods_target_key: 商品目标在字段中的key
        :return:
        """
        # 品类
        name = dict_.get(category_key)
        # 标题必须忽略的字符
        ignore_name_list = dict_.get('ignoreNameList')
        ignore_name_list = ignore_name_list if ignore_name_list else []
        # 标题必须包含的字符
        contain_name_list = contain_name_list = dict_.get('containNameList')
        contain_name_list = contain_name_list if contain_name_list else []
        # 数据周期
        date_cycle = dict_.get('dateCycle')
        if date_cycle == 7:
            date_cycle = "7天"
        elif date_cycle == 30:
            date_cycle = "30天"
        # 商品目标列表
        goods_feature_list = dict_.get(goods_target_key)
        goods_feature_list = [
            GoodsFeature(
                goods_id=goods_feature.get('productId'),
                price_scope=goods_feature.get("priceScope"),
                competing1=goods_feature.get("competing1"),
                competing2=goods_feature.get("competing2")
            ) for
            goods_feature in goods_feature_list] if goods_feature_list else []

        return CategorySearch(name,
                              date_cycle=date_cycle,
                              ignore_name_list=ignore_name_list,
                              contain_name_list=contain_name_list,
                              goods_feature_list=goods_feature_list)


def wait_tb_complete(page: WebPage, open_error: bool = True, delay: int = 3, loading_time: int = 20):
    """
    等待表格加载完毕
    :param open_error: 是否开启抛出异常
    :param page: 网页对象
    :param delay: 延迟 默认3秒
    :param loading_time: 等待元素时长
    """
    if not wait_ele_disappear(page, ".oui-dt-message-content oui-dt-message-content-hasMask",
                              timeout=loading_time) and open_error:
        raise RuntimeError("等待表格加载数据失败")
    time.sleep(delay)


def get_xws_copy_action_content(page: WebPage, th_list: List[ChromiumElement], expected_col: int, copy_element: str) -> \
        Optional[str]:
    """
    获取小旺神一键复制操作生成的内容
    :param page: 网页对象
    :param th_list: 表头元素 用于校验列
    :param expected_col: 预期有多少列
    :param copy_element: 一键复制元素定位字符串
    :return: 获取正文成功 返回正文 列预期不对 返回None
    """
    try:
        result = None
        if len(th_list) == expected_col:
            Tap(page(copy_element), "点击小旺神一键复制失败", after_delay=(2, 3))()
            result = pyperclip.paste()
    finally:
        ActionChains(page).key_down(Keys.ESCAPE)
    return result
